import { KeepStencilOp, NotEqualStencilFunc, ReplaceStencilOp, ZeroStencilOp } from "three/src/constants";
import { App, Circle, Point } from "../../Engine";
import Const from "../../application/constants/Const";
import Events from "../../application/constants/Events";
import { InteractionEvent } from "../../processor/Mouse";


export default class EditCircle {
    private app: App;
    private innerCircle: Circle;
    private outerCircle: Circle;
    private ourterCircleWidth: number = 2;
    private param: {circleColor: string, circleOpacity: number, ourterCircleColor: string, ourterCircleWidth: number};
    private isOpen: boolean = false;
    private finishClickListener: Function;

    /**
     * 圆形编辑
     */
    constructor() {
        this.app = App.getInstance();
    }

    /**
     * 开启圆的编辑
     * @param param 编辑圆需要的参数
     * @param param.circleColor 圆形颜色
     * @param param.ourterCircleColor 圆形外圈颜色 默认为圆形颜色
     * @param param.ourterCircleWidth 圆形外圈宽度 默认2
     * @param param.circleOpacity 圆形透明度
     * @param param.depthTest 是否开启深度测试, 可选参数，默认为false
     * @param finishClickListener 编辑完成后的回调函数, 该函数有一个参数，为圆的mesh
     * @example var circleData = {circleColor: '#00FA9A', circleOpacity: 0.7};
            let finishClickListener = function(circle){
                console.log(circle);
            }
            editCircle = new GE.EditCircle(circleData, finishClickListener);
            editCircle.openEdit(); //开启编辑
            //editCircle.closeEdit(); //关闭编辑
     */
    public openEdit(param, finishClickListener: Function){
        if (this.isOpen) {
            return;
        }

        this.param = param;
        if(!param.ourterCircleColor){
            this.param.ourterCircleColor = param.circleColor;
        }
        if(!param.ourterCircleWidth){
            this.param.ourterCircleWidth = this.ourterCircleWidth;
        }
        this.finishClickListener = finishClickListener;

        this.register();
        this.isOpen = true;
    }

    /**
     * 关闭圆的编辑
     */
    public closeEdit(){
        this.app.remove(this.innerCircle);
        this.app.remove(this.outerCircle);
        this.cancleEvent();
        this.isOpen = false;
    }
    
    private register() {
        this.app.on(Events.Click, this.handleLeftClickEvent, this);
        this.app.on(Events.MouseMove, this.handleMoveEvent, this);
        this.app.on(Events.RightClick, this.handleRightClickEvent, this);
        
        this.app.mouse.addRaycasterType(Events.MouseMove);  //开启鼠标移动时的射线拾取功能
    }

    private cancleEvent() {
        this.app.off(Events.Click, this.handleLeftClickEvent, this);
        this.app.off(Events.MouseMove, this.handleMoveEvent, this);
        this.app.off(Events.RightClick, this.handleRightClickEvent, this);

        this.app.mouse.removeRaycasterType(Events.MouseMove);  //关闭鼠标移动时的射线拾取功能
    }

    private handleLeftClickEvent(data: InteractionEvent) {
        let clickPoint: Point = data.lnglat;
        clickPoint.toEPSGWeb();

        if (!this.innerCircle) {
            this.innerCircle = new Circle({center: clickPoint, radius: 0, color: this.param.circleColor, opacity: this.param.circleOpacity});
            this.innerCircle.material['stencilWrite'] = true;
            this.innerCircle.material['stencilRef'] = Const.StencilRefValue.EditCricleRef;
            this.innerCircle.material['stencilFuncMask'] = 0xff;
            this.innerCircle.material['stencilFunc'] = NotEqualStencilFunc;
            this.innerCircle.material['stencilFail'] = KeepStencilOp;
            this.innerCircle.material['stencilZFail'] = KeepStencilOp;
            this.innerCircle.material['stencilZPass'] = ReplaceStencilOp;
            this.innerCircle.renderOrder = Infinity;
            this.app.add(this.innerCircle);

            this.outerCircle = new Circle({center: clickPoint, radius: 0, color: this.param.circleColor, opacity: this.param.circleOpacity});
            this.outerCircle.material['stencilWrite'] = true;
            this.outerCircle.material['stencilRef'] = Const.StencilRefValue.EditCricleRef;
            this.outerCircle.material['stencilFuncMask'] = 0xff;
            this.outerCircle.material['stencilFunc'] = NotEqualStencilFunc;
            this.outerCircle.material['stencilFail'] = KeepStencilOp;
            this.outerCircle.material['stencilZFail'] = KeepStencilOp;
            this.outerCircle.material['stencilZPass'] = ZeroStencilOp;
            this.outerCircle.setColor(this.param.ourterCircleColor);
            this.outerCircle.renderOrder = Infinity;
            this.app.add(this.outerCircle);
        }else{
            this.cancleEvent();
            if(this.finishClickListener){
                this.finishClickListener(this.outerCircle);
            }
        }
    }

    private handleMoveEvent(data: InteractionEvent) {
        if (!this.innerCircle) {
            return;
        }
        let clickPoint: Point = data.lnglat.clone();
        clickPoint.toEPSGWeb();

        let center = this.innerCircle.getParam().center;
        let radius = center.distanceTo(clickPoint);
        this.innerCircle.setRadius(radius - this.param.ourterCircleWidth);

        this.outerCircle.setRadius(radius);
    }

    
    private handleRightClickEvent(data: InteractionEvent) {
        if (!this.innerCircle) {
            return;
        }
        let clickPoint: Point = data.lnglat.clone();
        clickPoint.toEPSGWeb();

        this.cancleEvent();

        let center = this.innerCircle.getParam().center;
        let radius = center.distanceTo(clickPoint);
        this.innerCircle.setRadius(radius - this.param.ourterCircleWidth);

        this.outerCircle.setRadius(radius);

        if(this.finishClickListener){
            this.finishClickListener(this.outerCircle);
        }
    }
}